
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <sys/errno.h>
#include <netinet/in.h>

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//#include "config.h"

#define BUFSIZE 256

void reaper(int);
int  passiveTCP(const char *server, int qlen);
int  errexit(const char *format, ...);

int  Server(int fd);

unsigned int buffer[64];
void MakePackage(unsigned Type, unsigned int Device, unsigned int Command, unsigned int Data);

int ClientAlive = 0;
int ClientFd;
int TerminalAlive = 0;
int TerminalFd;

int main(int argc, char *argv[]) {

	int server_sockfd;
	int client_sockfd;
	int len;
	struct sockaddr_in my_addr;
	struct sockaddr_in remote_addr;
	unsigned int sin_size;
	char buf[BUFSIZ];
	int result;

	server_sockfd = passiveTCP("8001", 5);

	(void) signal(SIGCHLD, reaper);

	// 
	
	while(1) {

		sin_size = sizeof(struct sockaddr_in);

		client_sockfd = accept(server_sockfd, (struct sockaddr *)&my_addr, &sin_size);
		if (client_sockfd < 0) {
			if (errno == EINTR)
			  continue;
			errexit("accpet: %s\n", strerror(errno));
		}

		switch(fork()) {
		case 0:
			// child
			(void) close(server_sockfd);
			exit(Server(client_sockfd));
		default:
			// parent
			(void) close(client_sockfd);
			break;
		case -1:
			errexit("fork: %s\n", strerror(errno));
		}

	}

}

int Server(int fd) {

	unsigned int recv_buf[64];
	unsigned int send_buf[64];
	int recv_cnt;
	int send_cnt;
	int BadPackage;

	while (recv_cnt = read(fd, recv_buf, 256)) {
		
		if (recv_cnt < 0)
		  errexit("echo read: %s\n", strerror(errno));
	
		BadPackage = 0;

		// Check Package Head
		if (recv_buf[0] != 0xAAAAAAAA) {
			BadPackage = 1;
		}else {
			
			// Check Package Type
			switch(recv_buf[1]) {
				
				case 0xA0000001: // Client Alive
					{
						if (!ClientAlive)
						  ClientAlive = 1;
						ClientFd = fd;
						printf("Client Alive. %d\n", ClientFd);
						break;
					}
				case 0xA0000000: // Client DOwn
					{
						if (ClientAlive)
						  ClientAlive = 0;
						printf("Client Down.\n");
						break;
					}
				case 0xA0000002: // Device Control Request
					{
						printf("Device Control.\n");
						if (TerminalAlive) {
							send_cnt = write(TerminalFd, recv_buf, 256);
							if (send_cnt < 0)
								errexit("send package to Terminal, %s\n", strerror(errno));
							recv_cnt = read(TerminalFd, recv_buf, 256);
							if (recv_cnt < 0)
								errexit("receive package from Terminal, %s\n", strerror(errno));
							send_cnt = write(ClientFd, recv_buf, 256);
							if (send_cnt < 0)
								errexit("send package to Client, %s\n", strerror(errno));
						}else {
							printf("Terminal is NOT Alive!\n");
							MakePackage(0xC0000000, 0, 0, 0);
							send_cnt = write(ClientFd, buffer, 256);
							if (send_cnt < 0)
							  errexit("send package to Client, %s\n", strerror(errno));
						}
						break;
					}
				case 0xC0000001:
					{
						if (!TerminalAlive)
						  TerminalAlive = 1;
						TerminalFd = fd;
						printf("Terminal Alive. %d\n", TerminalFd);
						break;
					}
				case 0xC0000000:
					{
						if (TerminalAlive)
						  TerminalAlive = 0;
						printf("Terminal Down.\n");
						break;
					}
				case 0xC0000002:
					{
						printf("Device Control Acknowledge.\n");
						if (ClientAlive) {
							send_cnt = write(ClientFd, recv_buf, 256);
							if (send_cnt < 0)
							  errexit("send package to Client, %s\n", strerror(errno));
							recv_cnt = read(ClientFd, recv_buf, 256);
							if (recv_cnt < 0)
								errexit("recv package from Client, %s\n", strerror(errno));
							send_cnt = write(TerminalFd, recv_buf, 256);
							if (send_cnt < 0)
								errexit("send package to Client, %s\n");
						}else {
							printf("Client is NOT Alive! \n");
							MakePackage(0xA0000000, 0, 0, 0);
							send_cnt = write(TerminalFd, buffer, 256);
							if (send_cnt < 0)
							  errexit("send package to Terminal, %s\n", strerror(errno));
						}
						break;
					}
				default:
					{
						printf("unknow package type.\n");
						MakePackage(0xF0000000, 0, 0, 0);
						while(send_cnt = write(fd, buffer, 256)) {
							if (send_cnt < 0)
							  errexit("send package , %s\n", strerror(errno));
						}
					}
			}

		}
	}

}

void MakePackage(unsigned int Type, unsigned int Device, unsigned int Command, unsigned int Data) {

	memset(buffer, sizeof(buffer), 0);
	buffer[0] = 0xAAAAAAAA;
	buffer[1] = Type;
	buffer[2] = Device;
	buffer[3] = Command;
	buffer[4] = Data;
	buffer[63] = 0xFFFFFFFF;

}


void reaper(int sig) {
	int status;
	while(wait3(&status, WNOHANG, (struct rusage *)0) >= 0)
	  ;
}

























